#include "Matrix.h"
#include <cmath>
Matrix::Matrix(size_t h, size_t w)
{
    this->_h = h;
    this->_w = w;
    this->_mat = vector<vector<long double>>(h);
    for (auto& i : this->_mat)
        i = vector<long double>(w);
}


Matrix::Matrix(size_t h, size_t w, vector<vector<long double>> mat)
{
    this->_h = h;
    this->_w = w;
    if (mat.size() != h)
    {
        throw "invalid Matrix subscript";
        return;
    }
    for (auto& i : mat)
        if (i.size() != w)
        {
            throw "invalid Matrix subscript";
            return;
        }
    this->_mat = mat;
}



Matrix::Matrix(size_t h, size_t w, const std::initializer_list<std::initializer_list<long double>>& il)
{
    this->_h = h;
    this->_w = w;
    this->_mat = vector<vector<long double>>(h);
    for (auto& i : this->_mat)
        i = vector<long double>(w);
    if (il.size() != h)
    {
        throw "invalid Matrix subscript";
        return;
    }
    size_t i = 0;
    for (auto iter = il.begin(); i < h; i++, iter++)
    {
        if ((*iter).size() != w)
        {
            throw "invalid Matrix subscript";
            return;
        }
        this->_mat[i] = *iter;
    }
}


Matrix::Matrix(const Matrix& mat)
{
    this->_h = mat._h;
    this->_w = mat._w;
    this->_mat = mat._mat;
}


void Matrix::put()
{
    for (size_t i = 0; i < this->_h; i++)
    {
        for (size_t j = 0; j < this->_w; j++)
        {
            std::cout << this->_mat[i][j] << " ";
        }
        std::cout << std::endl;
    }
}


size_t Matrix::height() const
{
    return size_t(this->_h);
}


size_t Matrix::width() const
{
    return size_t(this->_w);
}


long double& Matrix::at(size_t h, size_t w)
{
    if (h >= this->_h || w >= this->_w)
    {
        throw "invalid Matrix subscript";
    }
    return this->_mat[h][w];
}


const Matrix Matrix::operator*(const Matrix& b)
{
    if (this->_w != b._h)
    {
        return Matrix(0, 0);
    }
    Matrix MatAns(this->_h, b._w);
    for (size_t i = 0; i < this->_h; i++)
    {
        for (size_t j = 0; j < b._w; j++)
        {
            long double ans = long double(0);
            for (size_t k = 0; k < this->_w; k++)
            {
                ans = ans + this->_mat[i][k] * b._mat[k][j];
            }
            MatAns.at(i, j) = ans;
        }
    }
    return MatAns;
}

Matrix RotateMat(long double alpha)
{
    Matrix MatAns(2, 2, {
        {cos(alpha),-sin(alpha)},
        {sin(alpha),cos(alpha)}
        });
    return MatAns;
}
